﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace BlockOS
{
    public static class VoxelMath
    {
        public static IEnumerable<(int, int, int)> Cube(int fromX, int fromY, int fromZ, int toX, int toY, int toZ)
        {
            (fromX, toX) = fromX > toX ? (toX, fromX) : (fromX, toX);
            (fromY, toY) = fromY > toY ? (toY, fromY) : (fromY, toY);
            (fromZ, toZ) = fromZ > toZ ? (toZ, fromZ) : (fromZ, toZ);

            for (int x = fromX; x <= toX; x++)
            {
                for (int y = fromY; y <= toY; y++)
                {
                    for (int z = fromZ; z <= toZ; z++)
                    {
                        yield return (x, y, z);
                    }
                }
            }
        }

        public static IEnumerable<(int, int, int)> HeightMap(int fromX, int toX, int fromZ, int toZ, int[,] heightMap)
        {
            (fromX, toX) = fromX > toX ? (toX, fromX) : (fromX, toX);
            (fromZ, toZ) = fromZ > toZ ? (toZ, fromZ) : (fromZ, toZ);

            for (int x = fromX; x <= toX; x++)
            {
                for (int z = fromZ; z <= toZ; z++)
                {
                    int height = heightMap[x, z];
                    for (int y = 0; y < height; y++)
                    {
                        yield return (x, y, z);
                    }
                }
            }
        }

        // Bresenham
        public static IEnumerable<(int, int, int)> Line(int fromX, int fromY, int fromZ, int toX, int toY, int toZ)
        {
            yield return (fromX, fromY, fromZ);
        }

        // https://www.bilibili.com/read/cv10767706
        public static IEnumerable<(int, int, int)> Line(int x0, int y0, int x1, int y1)
        {
            int dx = Mathf.Abs(x1 - x0);  //计算起点和终点X，Y方向的距离
            int dy = Mathf.Abs(y1 - y0);
            bool bInterchange = false;  //位移方向
            int e, signX, signY, temp;
            signX = (x1 > x0) ? 1 : ((x1 < x0) ? -1 : 0);  //判断步长
            signY = (y1 > y0) ? 1 : ((y1 < y0) ? -1 : 0);
            if (dy > dx)  //斜率大于1的时候，Y变为主位移方向（交换dy与dx的值即可）
            {
                temp = dx;
                dx = dy;
                dy = temp;
                bInterchange = true;
            }
            e = -dx;  //e的初始值
            int x = x0, y = y0;
            for (int i = 0; i < dx; i++)
            {
                yield return (x, y, 4);
                if (!bInterchange)  //当X为主位移方向
                {
                    x += signX;
                }
                else //Y为主位移方向
                {
                    y += signY;
                }
                e += 2 * dy;
                if (e >= 0) //当E大于等于0的时候，需要增长Y的值和减小e的值
                {
                    if (!bInterchange)
                    {
                        y += signY;
                    }
                    else
                    {
                        x += signX;
                    }
                    e -= 2 * dx;
                }
            }
        }
    }
}
